package com.kmxd.ams.infra.aspect;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.kmxd.ams.client.archive.IArchiveFieldSvc;
import com.kmxd.ams.client.archive.IArchiveRuleMainSvc;
import com.kmxd.ams.client.archive.dto.ArchiveFieldQueryDTO;
import com.kmxd.ams.client.archive.vo.ArchiveFieldListVO;
import com.kmxd.ams.client.archive.vo.ArchiveRuleMainListVO;
import com.kmxd.ams.client.system.ISysDeptSvc;
import com.kmxd.ams.client.system.ISysDictItemSvc;
import com.kmxd.ams.client.system.ISysDictSvc;
import com.kmxd.ams.client.system.dto.SysDictQueryDTO;
import com.kmxd.ams.client.system.vo.SysDeptListVO;
import com.kmxd.ams.client.system.vo.SysDictItemListVO;
import com.kmxd.ams.client.system.vo.SysDictListVO;
import com.kmxd.ams.core.common.constant.Constants;
import com.kmxd.ams.core.common.enums.DictStorageEnum;
import com.kmxd.ams.core.result.R;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Service;

/**
 * 数据字典翻译
 *
 * @author ZuoLG
 */
@Aspect
@Service("DictAspect")
@Slf4j
public class DictAspect {

  /** 需要切面的方法名 */
  private final String methodName = "selectPage";
  /** 当前表字段信息 */
  @Resource private IArchiveFieldSvc archiveFieldSvc;
  /** 字典接口 */
  @Resource private ISysDictSvc sysDictSvc;
  @Resource private ISysDictItemSvc sysDictItemSvc;
  @Resource private ISysDeptSvc sysDeptSvc;
  @Resource private IArchiveRuleMainSvc archiveRuleMainSvc;

  /** 定义切点Pointcut */
  @Pointcut("execution(* com.kmxd.ams.controller.arrange.*.*(..))")
  public void excudeService() {}

  @Around("excudeService()")
  public Object doAround(ProceedingJoinPoint pjp) throws Throwable {

    long startTime = System.currentTimeMillis();
    Object result = pjp.proceed();
    log.debug("获取JSON数据 耗时：" + (System.currentTimeMillis() - startTime) + "ms");

    if (methodName.equals(pjp.getSignature().getName())) {
      long start = System.currentTimeMillis();
      this.parseDictText(result);
      log.debug("解析注入JSON数据 耗时：" + (System.currentTimeMillis() - start) + "ms");
    }
    return result;
  }

  /**
   * @param result
   */
  private void parseDictText(Object result) {
    if (result instanceof R) {
      String tableId = null;
      Object parameter = ((R) result).getParameter();
      if (ObjectUtil.isNotEmpty(parameter)) {
        tableId = JSONUtil.parseObj(parameter).getStr("tableId");
      }
      // 字段数据
      List<ArchiveFieldListVO> fields = Lists.newArrayList();
      if (ObjectUtil.isNotEmpty(tableId)) {
        ArchiveFieldQueryDTO queryDTO = new ArchiveFieldQueryDTO();
        queryDTO.setTableId(tableId);
        fields = archiveFieldSvc.selectList(queryDTO);
      }
      // 字典数据
      List<SysDictListVO> dicts = sysDictSvc.selectList(new SysDictQueryDTO());
      List<SysDictItemListVO> dictItem = sysDictItemSvc.selectListAll();
      // 查询所有部门
      List<SysDeptListVO> depts = sysDeptSvc.listAll();
      // 查询所有版本内容
      List<ArchiveRuleMainListVO> rules = archiveRuleMainSvc.selectListAll();
      if (((R) result).getData() instanceof IPage) {
        List<JSONObject> items = new ArrayList<>();
        for (Object record : ((IPage) ((R) result).getData()).getRecords()) {
          ObjectMapper mapper = new ObjectMapper();
          String json = "{}";
          try {
            // 解决@JsonFormat注解解析不了的问题详见SysAnnouncement类的@JsonFormat
            json = mapper.writeValueAsString(record);
          } catch (JsonProcessingException e) {
            log.error("json解析失败" + e.getMessage(), e);
          }
          JSONObject item = JSONObject.parseObject(json);
          String year = String.valueOf(item.get("year"));
          for (Field field : oConvertUtils.getAllFields(record)) {
            String oldValue = item.getString(field.getName());
            // 判断是否是部门翻译
            if ("fillingDepartment".equalsIgnoreCase(field.getName())
                && StrUtil.isNotBlank(oldValue)) {
              SysDeptListVO dept =
                  depts.stream()
                      .filter(x -> ObjectUtil.equals(x.getId().toString(), oldValue))
                      .findFirst()
                      .orElse(null);
              item.put(
                  field.getName(),
                  ObjectUtil.isNotEmpty(dept) && ObjectUtil.isNotEmpty(dept.getName())
                      ? dept.getName()
                      : oldValue);
            }
            // 固定处理版本名称问题
            else if ("archRuleId".equalsIgnoreCase(field.getName())
                && StrUtil.isNotBlank(oldValue)) {
              ArchiveRuleMainListVO version =
                  rules.stream()
                      .filter(x -> ObjectUtil.equals(x.getId().toString(), oldValue))
                      .findFirst()
                      .orElse(null);
              item.put(
                  field.getName(), ObjectUtil.isNotEmpty(version) ? version.getName() : oldValue);
            } else {
              // 翻译字典值对应的txt
              String textValue =
                  translateDictValue(
                      field.getName(), oldValue, fields, dicts, dictItem, year, field);
              item.put(field.getName(), textValue);
            }
          }
          items.add(item);
        }
        ((IPage) ((R) result).getData()).setRecords(items);
      }
    }
  }

  /**
   * 翻译字典文本
   *
   * @param key 翻译的字段
   * @param value 翻译的值
   * @return
   */
  private String translateDictValue(
      String key,
      String value,
      List<ArchiveFieldListVO> fields,
      List<SysDictListVO> dicts,
      List<SysDictItemListVO> dictItems,
      String year,
      Field fieldOld) {
    // 如果值为空不需要翻译
    if (oConvertUtils.isEmpty(value)) {
      return null;
    }
    ArchiveFieldListVO fieldDatePicker =
        fields.stream()
            .filter(
                x ->
                    StringUtils.underlineToCamel(x.getDbFieldKey()).equalsIgnoreCase(key)
                        && "DatePicker".equalsIgnoreCase(x.getWidget()))
            .findFirst()
            .orElse(null);
    if (ObjectUtil.isNotEmpty(fieldDatePicker)
        && ObjectUtil.isNotEmpty(fieldDatePicker.getWidget())) {
      try {
        // 此处只需要处理日期类型，年度无需处理，时间类型已经格式化
        return value.replace("00:00:00", "").trim();
      } catch (Exception e) {
        return value;
      }
    }
    // 判断字段是否需要翻译
    ArchiveFieldListVO field =
        fields.stream()
            .filter(
                x ->
                    StringUtils.underlineToCamel(x.getDbFieldKey()).equalsIgnoreCase(key)
                        && StrUtil.isNotBlank(x.getDictField()))
            .findFirst()
            .orElse(null);
    // 判断是否需要翻译
    if (ObjectUtil.isNull(field)) {
      return value;
    }
    SysDictListVO dict =
        dicts.stream()
            .filter(x -> x.getDictCode().equalsIgnoreCase(field.getDictField()))
            .findFirst()
            .orElse(null);

    int yearInt =
        oConvertUtils.isNotEmpty(year) && NumberUtil.isNumber(year)
            ? Integer.parseInt(year)
            : Constants.DEF_VERSION;
    // 找不到字典，直接返回
    if (ObjectUtil.isNull(dict) || ObjectUtil.isEmpty(yearInt) || oConvertUtils.isEmpty(yearInt)) {
      return value;
    }
    SysDictItemListVO dictItemNew =
        dictItems.stream()
            .filter(
                x ->
                    ObjectUtil.equals(x.getDictId(), dict.getId())
                        && (ObjectUtil.isEmpty(x.getVersion())
                                ? Constants.DEF_VERSION
                                : x.getVersion())
                            <= yearInt)
            .filter(
                dictItem -> {
                  if (ObjectUtil.isEmpty(field.getDictStorage())) {
                    return ObjectUtil.equals(dictItem.getDictItemCode(), value);
                  }
                  return ObjectUtil.equals(DictStorageEnum.VALUE.getType(), field.getDictStorage())
                      ? ObjectUtil.equals(dictItem.getDictItemCode(), value)
                      : ObjectUtil.equals(dictItem.getDictItemName(), value);
                })
            .findFirst()
            .orElse(null);

    // 找不到字典，直接返回
    if (ObjectUtil.isNull(dictItemNew)) {
      return value;
    }
    if (ObjectUtil.isEmpty(field.getDictShow())) {
      return dictItemNew.getDictItemCode();
    }
    return ObjectUtil.equals(DictStorageEnum.VALUE.getType(), field.getDictShow())
        ? dictItemNew.getDictItemCode()
        : dictItemNew.getDictItemName();
  }
}
